import 'dart:io';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logcat_viewer/logcat_viewer.dart';

class Status {
  static bool isLogPage = false;
}

class OverlayContainer extends StatefulWidget {
  final Widget child;
  final bool debug;// 只有为true的时候才会去获取log，显示进入查看log的悬浮窗
  const OverlayContainer({Key? key, required this.child, this.debug = false}) : super(key: key);

  @override
  _OverlayContainerState createState() => _OverlayContainerState();
}

class _OverlayContainerState extends State<OverlayContainer> {
  OverlayEntry? overlayEntry;
  double overlaySize = 80;
  Offset offset = Offset.zero;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      if (Platform.isAndroid && widget.debug) {// 目前只支持Android，IOS 暂时没有实现方案
        clickShow(context);
        // try {
        //   LogcatUtils.instance.startLog();
        // } on PlatformException {
        //   // platformVersion = 'Failed to get platform version.';
        // }
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
  clickShow(BuildContext context){
    if (overlayEntry != null) {
      return;
    }
    overlayEntry = _showOverlay(context);
    //往Overlay中插入插入OverlayEntry
    Overlay.of(context)!.insert(overlayEntry!);
  }

  OverlayEntry _showOverlay(BuildContext context) {
    OverlayEntry overlayEntry = OverlayEntry(builder: (context) {
      //外层使用Positioned进行定位，控制在Overlay中的位置
      // 控制不可拖出屏幕外

      MediaQueryData mediaQueryData = MediaQuery.of(context);
      Size screenSize = mediaQueryData.size;
      double screenWidth = screenSize.width;
      double screenHeight = screenSize.height;
      double dx = 20.0;
      double dy = 50;

      if ((offset.dx > 0) &&
          ((offset.dx + overlaySize) < screenWidth)) {
        dx = offset.dx;
      } else if ((offset.dx + overlaySize) >= screenWidth) {
        dx = screenWidth - overlaySize;
      } else {
        dx = 0;
      }

      if ((offset.dy > 0) &&
          ((offset.dy + overlaySize) < screenHeight)) {
        dy = offset.dy;
      } else if ((offset.dy + overlaySize) >= screenHeight) {
        dy = screenHeight - overlaySize;
      } else {
        dy = 20;
      }

      return Positioned(
        top: dy,
        left: dx,
        child: Draggable(
          feedback: _contentBody(context),
          child: _contentBody(context),
          childWhenDragging: Container(), //拖动过程回调
          onDraggableCanceled: (Velocity velocity, Offset offset) {
            setState(() {
              //第二个参数为拖动的动态坐标
              this.offset = offset;
            });
          },
        ),
      );
    });
    return overlayEntry;
  }

  Widget _contentBody(BuildContext context) {
    return Material(
      color: const Color(0x00FFFFFF),
      child: InkWell(
        onTap: () {
          if (Status.isLogPage) {
            return;
          }
          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (BuildContext context) => const ShowLogPage(),
              settings: const RouteSettings(name: "ShowLogPage"),
            ),
          );
        },
        child: Container(
          width: overlaySize,
          height: overlaySize,
          decoration: BoxDecoration(
            color: const Color(0x7FFFFFFF),
            borderRadius: BorderRadius.all(Radius.circular(overlaySize/2)),
          ),
          alignment: Alignment.center,
          child: const Text("查看log"),
        ),
      ),
    );
  }

  @override
  void dispose() {
    overlayEntry?.remove();//移除
    overlayEntry = null;
    try {
      LogcatUtils.instance.cancelListen();
    } on PlatformException {
      // platformVersion = 'Failed to get platform version.';
    }
    super.dispose();
  }

}

class ShowLogPage extends StatefulWidget {
  const ShowLogPage({Key? key}) : super(key: key);

  @override
  _ShowLogPageState createState() => _ShowLogPageState();
}

class _ShowLogPageState extends State<ShowLogPage> {
  List<String> _logList = [];
  bool stopScroll = false;
  late final ScrollController _controller = ScrollController();

  @override
  void dispose() {
    Status.isLogPage = false;
    LogcatUtils.instance.setFilterStr("");
    super.dispose();
  }
  @override
  void initState() {
    super.initState();
    Status.isLogPage = true;
    // Timer.periodic(const Duration(seconds: 1), (timer) {
    //   print("now print tick = ${timer.tick}");
    // });
    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      startLogInfo();
    });
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> startLogInfo() async {
    // String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      LogcatUtils.instance.startLog();
      LogcatUtils.instance.addListener((logList) {
        setState(() {
          _logList = logList;
          if (!stopScroll) {
            _controller.jumpTo(_controller.position.maxScrollExtent);
          }
        });
      });
    } on PlatformException {
      // platformVersion = 'Failed to get platform version.';
    }
  }
  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> stopLogInfo() async {
    // String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      LogcatUtils.instance.stopLog();
    } on PlatformException {
      // platformVersion = 'Failed to get platform version.';
    }
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> clearLogInfo() async {
    // String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      LogcatUtils.instance.clearLog();
    } on PlatformException {
      // platformVersion = 'Failed to get platform version.';
    }
  }

  @override
  void setState(VoidCallback fn) {
    if (mounted) {
      super.setState(fn);
    }
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: const Text("查看log信息",),
      ),
      body: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              // TextButton(
              //   onPressed: (){
              //     startLogInfo();
              //   },
              //   child: Text("开始"),
              // ),
              TextButton(
                onPressed: (){
                  // stopLogInfo();
                  stopScroll = !stopScroll;
                  if (!stopScroll) {
                    _controller.jumpTo(_controller.position.maxScrollExtent);
                  }
                },
                child: Text(stopScroll ? "继续滚动" : "停止滚动"),
              ),
              Expanded(
                child:  TextField(
                  onChanged: (value) {
                    LogcatUtils.instance.setFilterStr(value);
                  },
                  style: const TextStyle(color: Colors.black),
                  decoration: const InputDecoration(
                    border: InputBorder.none,
                    hintText: "输入筛选文字",
                    hintStyle: TextStyle(color: Colors.grey)
                  ),
                ),
              ),
              TextButton(
                onPressed: (){
                  clearLogInfo();
                },
                child: Text("清空"),
              ),
            ],
          ),
          Expanded(
            child: ListView(
              controller: _controller,
              children: _logList.map((log) => LogInfoItem(text: log)).toList(),
            ),
          )
        ],
      ),
    );
  }
}
class LogInfoItem extends StatelessWidget {
  final String text;
  const LogInfoItem({Key? key, required this.text}) : super(key: key);

  isError() {
    String lowerStr = text.toLowerCase();
    return lowerStr.contains("err") ;
  }

  List<InlineSpan> _getContentSpan() {
    List<InlineSpan> _contentList = [];

    RegExp exp =
    //new RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+');
    RegExp(r'(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?');
    // text = "如果www.baidu.com这是一段文本但是里面包含了连接";
    Iterable<RegExpMatch> matches = exp.allMatches(text);

    int index=0;
    Color textColor = isError() ? Colors.redAccent : Colors.black;
    for (var match in matches) {
      /// start 0  end 8
      /// start 10 end 12
      String c = text.substring(match.start, match.end);

      // print('---地址-url:--$c');
      if(match.start==index){
        index=match.end;
      }
      if(index<match.start){
        String a=text.substring(index+1,match.start);
        // print('---地址-内容AAAA--$a');
        index=match.end;
        _contentList.add(
          TextSpan(text: a, style: TextStyle(color: textColor)),
        );
      }

      if (exp.hasMatch(c)) {
        _contentList.add(
          TextSpan(
            text: c,
            style: const TextStyle(color: Colors.blue),
          ),
        );
      } else {
        _contentList.add(
          TextSpan(text: c,style: TextStyle(color: textColor)),
        );
      }
    }
    if(index<text.length){
      String a=text.substring(index,text.length);
      // print('---地址-内容BBBB--$a');
      _contentList.add(
        TextSpan(text: a, style: TextStyle(color: textColor)),
      );

    }


    return _contentList;
  }

  @override
  Widget build(BuildContext context) {
    // Widget child;

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      decoration: const BoxDecoration(
        border: Border(
          bottom: BorderSide(
            color: Colors.grey,
            width: 0.5,
          ),
        )
      ),
      child: RichText(
        text:TextSpan(
            children:  _getContentSpan()
        ),
      ),
    );
  }
}
